package com.book.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.book.dictionary.BookStatusEnum;
import com.book.exception.BusinessException;
import com.book.mapper.BooksMapper;
import com.book.model.dto.BookAddDTO;
import com.book.model.dto.BookQueryDTO;
import com.book.model.entity.*;
import com.book.model.vo.BookQueryMainVO;
import com.book.model.vo.BookQueryVO;
import com.book.model.vo.BookVO;
import com.book.service.*;
import com.book.util.SmsUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 书本表 服务实现类
 * </p>
 *
 * @author auto
 * @since 2025-04-02 06:38:55
 */
@Service
public class BooksServiceImpl extends ServiceImpl<BooksMapper, Books> implements BooksService {

    @Autowired
    private BookCategoryService bookCategoryService;

    @Autowired
    private BookDetailService bookDetailService;

    @Autowired
    private SmsUtil smsUtil;

    @Autowired
    private UserService userService;

    @Autowired
    private PointsRecordsService pointsRecordsService;
    @Override
    public BookQueryMainVO getBookListByPage(BookQueryDTO bookQueryDTO) {

        // 创建分页对象
        Page<Books> pageObj = new Page<>(bookQueryDTO.getPage(), bookQueryDTO.getSize());
        LambdaQueryWrapper<Books> queryWrapper = new LambdaQueryWrapper<>();
        if(StringUtils.isNotBlank(bookQueryDTO.getSearch())){
            queryWrapper.and(wrapper -> wrapper
                    .like(Books::getName, bookQueryDTO.getSearch())
                    .or()
                    .like(Books::getAuthor, bookQueryDTO.getSearch())
                    .or()
                    .like(Books::getBookCondition, bookQueryDTO.getSearch())
                    .or()
                    .like(Books::getIntroduction, bookQueryDTO.getSearch())
            );
        }

        if(StringUtils.isNotBlank(bookQueryDTO.getBookCategoryId())){
            queryWrapper.eq(Books::getBookCategoryId, bookQueryDTO.getBookCategoryId());
        }
        Page<Books> result = this.page(pageObj, queryWrapper);
        BookQueryMainVO  bookQueryMainVO = new BookQueryMainVO();
        bookQueryMainVO.setTotal((int) result.getTotal());
        LambdaQueryWrapper<BookDetail> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.in(BookDetail::getBookDetailId,result.getRecords().stream().map(Books::getBookDetailId).toArray());
        Map<String, BookDetail> bookDetailMap =bookDetailService.list(queryWrapper1).stream().collect(Collectors.toMap(BookDetail::getBookDetailId, bookDetail -> bookDetail));
        List<BookQueryVO> bookQueryVOList = new ArrayList<>();
        result.getRecords().forEach(book -> {
            BookQueryVO bookQueryVO = new BookQueryVO();
            BeanUtils.copyProperties(book, bookQueryVO);
            BeanUtils.copyProperties(bookDetailMap.get(book.getBookDetailId()), bookQueryVO);
            bookQueryVOList.add(bookQueryVO);
        });
        bookQueryMainVO.setRecords(bookQueryVOList);
        // 返回查询结果
        return bookQueryMainVO;
    }

    @Override
    public List<Books> getBookListByWxParam(String msg) {
        //对books中多个字段进行模糊查询
        LambdaQueryWrapper<Books> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(msg)) {
            queryWrapper.and(wrapper -> wrapper
                    .like(Books::getName, msg)
                    .or()
                    .like(Books::getAuthor, msg)
                    .or()
                    .like(Books::getBookCondition, msg)
                    .or()
                    .like(Books::getIntroduction, msg)
            );
        }else{
            return new ArrayList<>();
        }
        queryWrapper.in(Books::getStatusCode,Arrays.asList( BookStatusEnum.PENDING.getCode(), BookStatusEnum.CREATE.getCode(), BookStatusEnum.CANCEL.getCode(),BookStatusEnum.FINISH.getCode()));
        return this.list(queryWrapper);
    }

    @Override
    public List<Books> getBookListNewFile() {
        // 创建分页对象，查询第1页，每页5条数据
        Page<Books> page = new Page<>(1, 5);
        LambdaQueryWrapper<Books> queryWrapper = new LambdaQueryWrapper<>();
        // 按照创建时间降序排序
        queryWrapper.orderByDesc(Books::getCreateTime);
        // 执行分页查询
        Page<Books> result = this.page(page, queryWrapper);
        // 返回查询结果
        return result.getRecords();
    }

    @Override
    public List<Books> getPublishOrPurchase(boolean publish, String userId) {
        LambdaQueryWrapper<Books> queryWrapper = new LambdaQueryWrapper<>();
        if (publish) {
            queryWrapper.eq(Books::getUserId, userId);
        } else {
            queryWrapper.eq(Books::getDestination, userId);
        }
        return this.list(queryWrapper);
    }

    @Override
    public BookVO getBookById(String id) {
        Books book = this.getById(id);
        BookVO bookVO = new BookVO();
        BeanUtils.copyProperties(book, bookVO);
        BookCategory bookCategory = bookCategoryService.getById(book.getBookCategoryId());
        bookVO.setBookCategoryName(bookCategory.getCategory());
        return bookVO;
    }

    @Override
    public boolean createOrderBook(String bookId, String userId) {
        Books books = this.getById(bookId);
        User seller = userService.getById(books.getUserId());
        User buyer = userService.getById(userId);
//        检查积分是否足够
        if(books.getIsPoints() == 1){
            if(buyer.getPoints()<books.getPoints()){
                throw new BusinessException("积分不足");
            }else{
                seller.setPoints(seller.getPoints()+books.getPoints());
                buyer.setPoints(buyer.getPoints()-books.getPoints());
                pointsRecordsService.buyBook(userId, Long.valueOf(books.getPoints()),books.getName());
                pointsRecordsService.sellBook(books.getUserId(), Long.valueOf(books.getPoints()),books.getName());
                userService.updateById(seller);
                userService.updateById(buyer);
            }
        }
        books.setDestination(userId);
        books.setStatusCode(BookStatusEnum.PENDING.getCode());
        books.setStatusName(BookStatusEnum.PENDING.getName());
        books.setPurchaseDate(new Date());

        //发送短信通知
        String content = "您好，您的书籍《"+books.getName()+"》已被用户购买，请注意联系发货！";
        smsUtil.send(seller.getPhone(),content);
        return this.updateById(books);
    }

    @Override
    public boolean cancelOrderBook(String bookId) {
        Books books = this.getById(bookId);
        books.setStatusCode(BookStatusEnum.CANCEL.getCode());
        books.setStatusCode(BookStatusEnum.CANCEL.getName());
        User seller = userService.getById(books.getUserId());
        User buyer = userService.getById(books.getDestination());
        if(books.getIsPoints() == 1){
            seller.setPoints(seller.getPoints()-books.getPoints());
            buyer.setPoints(buyer.getPoints()+books.getPoints());
            pointsRecordsService.buyerCancelBook(books.getDestination(), Long.valueOf(books.getPoints()),books.getName());
            pointsRecordsService.sellerCancelBook(books.getUserId(), Long.valueOf(books.getPoints()),books.getName());
            userService.updateById(seller);
            userService.updateById(buyer);
        }
        return this.updateById(books);
    }

    @Override
    public boolean sendTelNotice(String bookId) {
        Books books = this.getById(bookId);
        User user = userService.getById(books.getDestination());
        String content = "您好，您的在二手平台买的书籍《"+books.getName()+"》已发货，请注意查收！";
        return smsUtil.send(user.getPhone(),content);
    }

    @Override
    public String userAddBook(BookAddDTO book) {
        //保存bookDetail表信息
        BookDetail bookDetail = new BookDetail();
        BeanUtils.copyProperties(book,bookDetail);
        bookDetailService.save(bookDetail);
        //保存book表信息
        Books books = new Books();
        BeanUtils.copyProperties(book,books);
        if(book.getChooseReuse() == 1){
            books.setStatusCode(BookStatusEnum.RESUE.getCode());
            books.setStatusName(BookStatusEnum.RESUE.getName());
        }else{
            books.setStatusCode(BookStatusEnum.CREATE.getCode());
            books.setStatusName(BookStatusEnum.CREATE.getName());
        }
        books.setCreateTime(new Date());
        books.setBookDetailId(bookDetail.getBookDetailId());
        this.save(books);

         //发放奖励积分
        PointsRecords pointsRecords = new PointsRecords();
        pointsRecords.setUserId(book.getUserId());
        pointsRecords.setPointsAmount(10L);
        pointsRecords.setDescription("发布书籍");
        pointsRecords.setRecordsType(0);
        pointsRecords.setCreateTime(new Date());
        pointsRecordsService.save(pointsRecords);

        User user = userService.getById(book.getUserId());
        user.setPoints(user.getPoints()+10);
        userService.updateById(user);
        return books.getBookId();
    }

    @Override
    public boolean confirmBook(String bookId) {
        Books books = this.getById(bookId);
        List<String> codeList = Arrays.asList(BookStatusEnum.PENDING.getCode(),BookStatusEnum.RESUE.getCode());
        if(!codeList.contains(books.getStatusCode())){
            throw new BusinessException("书籍状态错误，请刷新列表！");
        }
        books.setStatusCode(BookStatusEnum.FINISH.getCode());
        books.setStatusName(BookStatusEnum.FINISH.getName());
        return this.updateById(books);
    }

    @Override
    public Page<Books> publishQuery(BookQueryDTO dto) {

        Page<Books> page = new Page<>(dto.getPage(),dto.getSize());
        LambdaQueryWrapper<Books>  queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(dto.getSearch())) {
            queryWrapper.and(wrapper -> wrapper
                    .like(Books::getName, dto.getSearch())
                    .or()
                    .like(Books::getAuthor, dto.getSearch())
                    .or()
                    .like(Books::getBookCondition, dto.getSearch())
                    .or()
                    .like(Books::getStatusCode, dto.getSearch())
            );
        }
        queryWrapper.eq(Books::getChooseReuse,dto.getChooseReuse());
        return this.page(page,queryWrapper);
    }

    @Override
    public Books reuse(String bookId) {
        Books books = this.getById(bookId);
        if(books.getChooseReuse() == 1){
            books.setStatusCode(BookStatusEnum.FINISH.getCode());
            books.setStatusName(BookStatusEnum.FINISH.getName());
            this.updateById(books);
        }
        return books;
    }

    @Override
    public Books shelve(String bookId, Integer newCondition,Integer points) {
        Books books = this.getById(bookId);
        BookDetail detail = bookDetailService.getById(books.getBookDetailId());
        //全新：0.8，九成新0.6，八成新0.5，七成新0.4，六成新0.3，五成新以及以下0.2
        BigDecimal disCount = getDisCount(newCondition);
        //查出现有书籍的数量
        LambdaQueryWrapper<BookDetail> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BookDetail::getIsbn,detail.getIsbn());
        long countDetail = bookDetailService.count(queryWrapper);
        BigDecimal score = calculateScarcityScore(countDetail-1);
        BigDecimal price = books.getOriginPrice().multiply(disCount).multiply(score);
        books.setPrice(price);
        books.setUserId("550e8400-e29b-41d4-a716-446655440000");
        books.setDestination("");
        books.setStatusCode(BookStatusEnum.CREATE.getCode());
        books.setStatusName(BookStatusEnum.CREATE.getName());
        books.setBookCondition(newCondition+"成新");
        if(points>0){
            books.setIsPoints(1);
            books.setPoints(points);
        }else{
            books.setIsPoints(0);
            books.setPoints(0);
        }
        books.setDeliveryId(1);
        this.updateById(books);
        //现有价格=原价*折扣*稀缺度
        return books;
    }

    BigDecimal getDisCount(Integer newCondition){
        switch (newCondition) {
            case 10:
                return new BigDecimal(0.8);
            case 9:
                return new BigDecimal(0.6);
            case 8:
                return new BigDecimal(0.5);
            case 7:
                return new BigDecimal(0.4);
            case 6:
                return new BigDecimal(0.3);
            default:
                return new BigDecimal(0.2);
        }
    }



    BigDecimal calculateScarcityScore(long count){
        //常见书籍：0.8,数量>=50本
        //较稀缺书籍：1.0，数量>=20本
        //稀缺书籍：1.5，数量>=5本
        //绝版书籍：2.0，数量<5本
        if(count >= 50){
            return new BigDecimal(0.8);
        }else if(count >= 20){
            return new BigDecimal(1.0);
        }else if(count >= 5){
            return new BigDecimal(1.5);
        }else{
            return new BigDecimal(2.0);
        }
    }


}
